var l = console.log;
var { curry } = require("lodash");
// var compose = (f, g) => (x) => f(g(x));
var compose = (...args) => (...arguments) =>
  args.reduceRight((memo, cur) =>
    cur(typeof memo === "function" ? memo.apply(memo,arguments) : memo)
  );

//----------------------------
var toUpperCase = (x) => x.toUpperCase();
var exclaim = (x) => x + "!";
var shout = compose(exclaim, toUpperCase);

l(shout("hello"));

//----------------------------
// 尽管我们可以定义一个从左向右的版本，
// 但是从右向左执行更加能够反映数学上的含义——是的，组合的概念直接来自于数学课本。
var head = (x) => x[0];

var reduce = curry((f, init, arr) => arr.reduce(f, init));

//重点看一下这个reverse
var reverse = reduce((acc, x) => [x].concat(acc), []);

var last = compose(head, reverse);

l(last(["first", "second", "third"]));

// 结合律（associativity）
// var associative = compose(f, compose(g, h)) == compose(compose(f, g), h);
// true
//这个特性就是结合律，符合结合律意味着不管你是把 g 和 h 分到一组，还是把 f 和 g 分到一组都不重要。

var last2UpperCase =compose(toUpperCase,compose(head,reverse));
var last2UpperCase =compose(compose(toUpperCase,head),reverse);

var last2UpperCase = compose(exclaim,toUpperCase, head, reverse);

l(last2UpperCase(["first", "second", "third"]));
